﻿//
// $HeadURL: http://codeka-memcache.googlecode.com/svn/trunk/Codeka.Memcache/Config/ServerConfig.cs $
// $Revision: 8 $
// $Author: dean.codeka $     $Date: 2010-02-20 12:45:08 +0000 (Sat, 20 Feb 2010) $
//
// Copyright © 2009-2010 Dean Harding, all rights reserved.
//

using System.Net;
using System.Collections.Generic;
using System;

namespace Codeka.Memcache.Config
{
    /// <summary>
    /// This class represents the configuration information for a single memcache
    /// server.
    /// </summary>
    public class ServerConfig : IComparable<ServerConfig>
    {
        /// <summary>
        /// Gets or sets the relative "weight" of this server.
        /// </summary>
        /// <remarks>
        /// <para>If "Server A" has a <b>Weight</b> of 50 and "Server B" has a
        /// relative <b>weight</b> of 100, that means that "Server B" will get
        /// twice as many keys as "Server A". This setting is useful, for example,
        /// if you've got some servers with more memory than others - you want them
        /// to get keys approximately in the same ratio as available memory.</para>
        /// </remarks>
        public int Weight { get; set; }

        /// <summary>
        /// The <see cref="IPEndPoint"/> we'll be using to connect to this server.
        /// </summary>
        public IPEndPoint EndPoint { get; set; }

        /// <summary>
        /// Determines whether this <see cref="ServerConfig"/> refers to the same
        /// configuration as the given "other".
        /// </summary>
        public override bool Equals(object obj)
        {
            var other = obj as ServerConfig;
            if (other == null)
                return false;

            if (other.Weight != Weight)
                return false;

            if (other.EndPoint != EndPoint)
                return false;

            return true;
        }

        /// <summary>
        /// Gets a hashcode for this <see cref="ServerConfig"/>.
        /// </summary>
        public override int GetHashCode()
        {
            return Weight.GetHashCode() ^ EndPoint.GetHashCode();
        }

        /// <summary>
        /// Gets a string representation of this <see cref="ServerConfig"/>.
        /// </summary>
        public override string ToString()
        {
            return string.Format("{0}+{1}", EndPoint, Weight);
        }

        /// <summary>
        /// Compares this <see cref="ServerConfig"/> to the given <c>other</c> one.
        /// </summary>
        public int CompareTo(ServerConfig other)
        {
            int comp = Weight.CompareTo(other.Weight);
            if (comp == 0)
            {
                comp = EndPoint.AddressFamily.CompareTo(other.EndPoint.AddressFamily);
                if (comp == 0)
                {
                    comp = EndPoint.Port.CompareTo(other.EndPoint.Port);
                    if (comp == 0)
                    {
                        var thisAddr = EndPoint.Address.GetAddressBytes();
                        var otherAddr = other.EndPoint.Address.GetAddressBytes();

                        comp = thisAddr.Length.CompareTo(otherAddr.Length);
                        if (comp == 0)
                        {
                            for (int i = 0; i < thisAddr.Length; i++)
                            {
                                comp = thisAddr[i].CompareTo(otherAddr[i]);
                                if (comp != 0)
                                    break;
                            }
                        }
                    }
                }
            }

            return comp;
        }
    }
}
